/*****************************************************************************
 * Please See the declaration in the bottom of this file.
 *
 *
 * Version			Date				Comment
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * Init(0)			2007.11.19 
 *****************************************************************************/
 
 
//===============================
//INCLUDE FILES
//===============================
#include "..\h\SM59R16A2.h"
#include "..\h\SM59R16A2_ExtraDef.h"

#include "..\InternalEE\InternalEE.h"
#include "..\IO_7Segment\Segment7.h"
#include "..\Interrupt\Interrupt.h"
#include "..\Microwire\Microwire.h"
#include "..\MISC\4x4Keypad.h"
#include "..\MISC\Speaker.h"
#include "..\LCD\LCD16x2.h"
#include "..\MISC\Delay.h"
#include "..\ADC\ADC.h"
#include "..\PWM\PWM.h"
#include "..\IIC\IIC.h"
#include "..\Timer\Timer.h"


#include "..\[Demo]\Demo.h"



//===============================
//EXTERNAL VARIABLES
//===============================



//===============================
//DEFINITIONs
//===============================
#define		MenuMax			0x60
#define		SubMenu			0x01


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// The 64-pin demo board use 22.1184MHz as system clock.  //
// Timer 0 uses system clock by 12 as clock source.       //
// 22.1184/12 = 1.8432MHz.                                //
// (1/1.8432MHz)*18432 = 10ms.                            //
//                                                        //
// Therefore, if we want timer0 interrupt every 20ms,     //
// The timer 0 should count 18432*2 = 36864, then         //
// interrupt.                                             //
// The TH0 and TL0 should be setted to 65535-36864.       //
// That is 28671.                                         //                                 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
#define  	T0ReloadValue		28671



//===============================
//OWNED SUBROUTINES
//===============================



//===============================
//GLOBAL VARIABLES
//===============================
unsigned char		MenuIndex=0x00;
unsigned char		ADCDone, SW15Pressed, SW16Pressed;
bit			Timer0OverFlow;


unsigned char code	EDID_Data[]=
{
  0x09, 0x08, 0x10, 0x00, 0x00, 0x06, 0x05, 0x00, 0xEC, 0x15, 0xCD, 0x08, 0xC9, 0xC0, 0x00, 0x00,
  0x06, 0x03, 0x00, 0x00, 0xE1, 0x00, 0x02, 0x00, 0xB0, 0x04, 0xC1, 0x00, 0x02, 0x00, 0x00, 0x00,
  0xE2, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x70, 0x00, 0x07, 0x00, 0x00, 0x53, 0x74, 0x61, 0x6E, 0x6C,
  0x65, 0x79, 0x20, 0x20, 0x20, 0x20, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x30, 0x30, 0x3B, 0x5C, 0x2D,
  0x22, 0x24, 0x22, 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x30, 0x30, 0x1E, 0x04, 0x23, 0x00, 0x0B,
  0x00, 0x1E, 0x00, 0x00, 0x11, 0x24, 0x22, 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x30, 0x30, 0x3B,
  0x5B, 0x52, 0x65, 0x64, 0x5D, 0x5C, 0x2D, 0x22, 0x22, 0x24, 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E,
  0x30, 0x30, 0x1E, 0x04, 0x35, 0x00, 0x2A, 0x00, 0x30, 0x00, 0x00, 0x5F, 0x2D, 0x22, 0x24, 0x22
};  // 128Byte


//=============================================================================
// We define this area(for example, 0xFC00~0xFDFF) 512 Bytes as the internal 
// Virtual EEPROM area.
// The definition here is to reserve this area to prevent compiler destruction.
// !! [[ YOU CAN DEFINE ANY EMPTY AREA, ANY SIZE YOU WANT ]] !!!!
//=============================================================================
#define			EEROMAREA_START			0xFC00
unsigned char code	EEROMArea[512]		_at_	EEROMAREA_START;



//=============================================================================================
//
//=============================================================================================
void SYSTEM_INIT()
{
	
  LCD_Init();
  Delay10mSec(10);
  
  PrintLcdStrLX(1,0, "     SyncMOS    ");
  PrintLcdStrLX(2,0, " SM59R16A2 Demo ");
  Delay10mSec(300);


  P2 = 0x00;					// P2 is 7 Segment. for test only

  // Initialize External INT
  Int0Init( EXINT0_EN, INT0_FALLEDGE );
  Int1Init( EXINT1_EN, INT1_FALLEDGE );
  

  // Initialize ADC
  ADCInit(ADCC3_EN|ADCC2_EN|ADCC1_EN|ADCC0_EN, ADC_10BIT|ADC_CLK_DIV8);
  ADCInt_EN();					// Enable ADC interrupt
 

  // Initialize IIC
  IICInit(IIC_EN|IIC_MASTER|IIC_ADR_CA1|IIC_BR64);  


  // Initialize SPI module
  SPIInit(SPI_EN|SPI_MASTER|SPI_CKP_LOW|SPI_CKE_FALL|SPI_BR64, SPI_FULLDUP_DIS, SPI_MSB_FIRST);


  // Initialize Timer0
  Timer0_Init( T0_16B_MODE, T0ReloadValue );	// Set Timer 0 as 16 bit
  Timer0_IntEN(0);				// Set Timer 0 interrupt priority as 0 						
  Timer0_Run();	
  
  
  //
  SW15Pressed = false;
  SW16Pressed = false;
  
}



//=============================================================================================
//Shift to the next main menu item, when SW15 pressed.
//=============================================================================================
void Int0ISR(void) interrupt 0 using 0
{
	
  //Clear TCON_IE0 Flag. This flag can be cleared by software 
  //and is automatically cleared when interrupt is processed
  //INT0IF = false;

  SW15Pressed = true;
  
  BeepCount(1, 1200, 25);
  
  if((MenuIndex & SubMenu))			// In Sub menu, currently. No response.
   ;
  else
  {						// Shift to the next Menu
   	if(MenuIndex == MenuMax)
  	{
  		MenuIndex = 0x00;
 	}
  	else
  	{
  	
  		MenuIndex += 0x10;
  	}
  }
  
 INT0IF = false;				// Clear again to debounce.
  
}


//=============================================================================================
//
//=============================================================================================
void Timer0ISR (void) interrupt 1 using 1
{
	
  //Clear Timer0 Flag. This flag can be cleared by software 
  //and is automatically cleared when ISR is processed
  
  SetTimer0Value( T0ReloadValue );
  
  Timer0OverFlow = true; 
}


//=============================================================================================
//Enter to SubMenu or return to the Main Menu
//=============================================================================================
void Int1ISR(void) interrupt 2 using 0
{
	
  //Clear TCON_IE0 Flag. This flag can be cleared by software 
  //and is automatically cleared when interrupt is processed
  //INT0IF = false;
  SW16Pressed = true;

  BeepCount(1, 1200, 25);

  
  if(MenuIndex & SubMenu)
  {
  	MenuIndex &= 0xf0;			// Return to Main Menu 
  }
  else
  {
  	MenuIndex += SubMenu;			// Go into Sub Menu
  }
  
  INT1IF = false;				// Clear again to debounce.
  
}


//=============================================================================================
//
//=============================================================================================
void ADCISR(void) interrupt 10 using 3		// ADC Interrupt Vector Address 0053h => interrupt 10
{
	
  IRCON		&= (~ADC_IF);			// A/D converter interrupt flag, must be cleared by software

  ADCDone	= true;

}


//=============================================================================================
//Demo item (0)
//=============================================================================================
void Demo7Segment()
{
	
  unsigned char		Counter = 99;
  
  PrintLcdStrLX(1,0, "I/O,7Segmen Demo");
  PrintLcdStrLX(2,0, "Prs SW16 to Stop");
  			  
  while(!SW16Pressed)
  {
	if(Counter)
	{
		Wr7SegmentDec(Counter);
		Delay10mSec(100);
		Counter --;
	}
	else
	{
		Counter = 99;
	}
  }

}


//=============================================================================================
//Demo item (1)
//=============================================================================================
void DemoADC()
{
  
  UWORD		temp;
  
  ADCInit(ADCC3_EN|ADCC2_EN|ADCC1_EN|ADCC0_EN, ADC_10BIT|ADC_CLK_DIV8); 
  PrintLcdStrLX(1, 0, "10bit ADC Demo  ");
  PrintLcdStrLX(2, 0, "VR1=            ");

  while(!SW16Pressed)
  {	
  	
  	// Get ADC channel 0 (VR1) data
  	ADCDone = false;
	ADC_ChannelSel(ADC_CH0_IN);
	ADCStart();
	while( !ADCDone );
	temp.UByte[1] = ADCDL;
	temp.UByte[0] = ADCDH;
	
	PrintLcdStrLX(2, 4, "    ");		// Clear number
	SetCursorAddr(2, 4);
	PrintLcdDec(temp.UInt);			// Write new number

		
  	/* Get ADC channel 1 (VR2) data
	ADCDone = false;
	ADC_ChannelSel(ADC_CH1_IN);
	ADCStart();
	while( !ADCDone );
	temp.UByte[1] = ADCDL;
	temp.UByte[0] = ADCDH;
	
	PrintLcdStrLX(2,  , "    ");		// Clear number
	SetCursorAddr(2,  );
	PrintLcdDec(temp.UInt);			// Write new number
	*/

  	/* Get ADC channel 2 (Voltage Divider) data
  	ADCDone = false;
	ADC_ChannelSel(ADC_CH2_IN);
	ADCStart();
	while( !ADCDone );
	temp.UByte[1] = ADCDL;
	temp.UByte[0] = ADCDH;
	
	PrintLcdStrLX(2, 6, "    ");		// Clear number
	SetCursorAddr(2, 6);
	PrintLcdDec(temp.UInt);			// Write new number
	*/

  	/* Get ADC channel 3 (Thermal sensor) data
  	ADCDone = false;
	ADC_ChannelSel(ADC_CH3_IN);
	ADCStart();
	while( !ADCDone );
	temp.UByte[1] = ADCDL;
	temp.UByte[0] = ADCDH;
	
	PrintLcdStrLX(2, 4, "    ");		// Clear number
	SetCursorAddr(2, 4);
	PrintLcdDec(temp.UInt);			// Write new number
	*/
	
	Delay1mSec(50);			// For display stable.
  }
  
}


//=============================================================================================
//Demo item (2)
//=============================================================================================
void Demo4x4Keypad()
{


  unsigned char		temp;
  
  PrintLcdStrLX(1, 0, "Keypad Demo     ");
  PrintLcdStrLX(2, 0, "Prs SW16 to Stop");
  
  while(!SW16Pressed)
  {
  	
    	if( Timer0OverFlow )
  	{
 		Timer0OverFlow = false;
  		
  		temp = ScanKeypad();
  		
  		if( temp < 16 )
  			Wr7SegmentDec(temp);
  		else
	  		Seg7_Port = 0xff;
  	}
  }
}


//=============================================================================================
//Demo item (3)
//=============================================================================================
void DemoIntEE()
{


  unsigned char  	ErrorCount=0, i ;

  PrintLcdStrLX(1, 0, "Internal EE demo");
  
  while(!SW16Pressed)
  {

	//
	PrintLcdStrLX(2, 0, "Writing...      ");
	for (i=0; i<128; i++)				// Write 128 bytes
	{
		SetCursorAddr(2, 13);
		PrintLcdDec(i);
		PMEE_ByteWrite(EEROMAREA_START+i, EDID_Data[i]);
		Delay10mSec(2);				// For display stable.
  	}
        
 	PrintLcdStrLX(2, 0, "Done.           ");
	Delay10mSec(100);

	//	
  	if(!SW16Pressed)				// If User press SW16, then skip.
  	{
  		ErrorCount = 0;
 		PrintLcdStrLX(2, 0, "Verifying...    ");	
		for (i=0; i<128; i++)
		{
			SetCursorAddr(2, 13);
			PrintLcdDec(i);
			
			if( PMEE_ByteRead(EEROMAREA_START+i) != EDID_Data[i] )
			{
				ErrorCount ++;
			}
			Delay10mSec(2);			// For display stable.
  		}
  		
  		//
 		PrintLcdStrLX(2, 0, "Write OK. Err   ");
 		SetCursorAddr(2, 14);
		PrintLcdDec(ErrorCount);

 		Delay10mSec(200);
 	}
 	
  }  // End of while(!SW16Pressed)
 	
}


//=============================================================================================
//Demo item (4)
//
//The I2C EEPROM on the 64-pin demo board is 24LC04B.
//That is 8 bits organization EEPROM with two bloack of 256 bytes.
//=============================================================================================
void DemoIIC()
{

  unsigned char  	ErrorCount=0, i, temp ;

  PrintLcdStrLX(1, 0, "IIC demo:24xx EE");
  
  while(!SW16Pressed)
  {

	//
	PrintLcdStrLX(2, 0, "Writing...      ");
	for (i=0; i<128; i++)				// Write 128 bytes
	{
		SetCursorAddr(2, 13);
		PrintLcdDec(i);
		IICEE_ByteWrite(0, i, EDID_Data[i]);	// Write EDID_Data[] to I2C EE from bank 0, addr i
		Delay10mSec(2);				// Delay 10ms to wait EEPROM write completed
							// and 10ms for display stable
  	}
        
 	PrintLcdStrLX(2, 0, "Done.           ");
	Delay10mSec(100);

	//	
  	if(!SW16Pressed)				// If User press SW16, then skip.
  	{
  		ErrorCount = 0;
 		PrintLcdStrLX(2, 0, "Verifying...    ");	
		for (i=0; i<128; i++)
		{
			SetCursorAddr(2, 13);
			PrintLcdDec(i);
			temp = IICEE_RandomRead(0, i);
			if( temp != EDID_Data[i] )
			{
				ErrorCount ++;
			}
			Delay10mSec(2);			// For display stable.
  		}
  		
  		//
 		PrintLcdStrLX(2, 0, "Write OK. Err   ");
 		SetCursorAddr(2, 14);
		PrintLcdDec(ErrorCount);		
		Delay10mSec(200);
 	}
 	
  }  // End of while(!SW16Pressed)
 		
}


//=============================================================================================
//Demo item (5)
//
//The Microwire EEPROM on the 64-pin demo board is 93LC46B.
//That is 16 bits organization EEPROM with 64 words.
//=============================================================================================
void DemoMicrowire()
{

  unsigned char  	ErrorCount=0, i;

  PrintLcdStrLX(1, 0, "MW demo:93xx EE");
  
  while(!SW16Pressed)
  {

  	//
  	MWEE_EWEnable();
  	
	PrintLcdStrLX(2, 0, "Writing...      ");
	
	for (i=0; i<64; i++)
	{
		SetCursorAddr(2, 14);
		PrintLcdDec(i);
		MWEE_WordWrite(i, EDID_Data[i]);	// Write EDID_Data[] 64 bytes to Microwire EE from addr i.
		MWEE_ChkRdy();
		Delay10mSec(2);				// For display stable.
  	}
  	
 	MWEE_EWDisable();
 	        	
 	PrintLcdStrLX(2, 0, "Done.           ");
	Delay10mSec(100);


	//	
  	if(!SW16Pressed)				// If User press SW16, then skip.
  	{
  		
  		ErrorCount = 0;
 		PrintLcdStrLX(2,0, "Verifying...    ");	
 		
		for (i=0; i<64; i++)
		{
			SetCursorAddr(2, 14);
			PrintLcdDec(i);
			
			if( (unsigned char)MWEE_WordRead(i) != EDID_Data[i] )
			{
				ErrorCount ++;
			}
			Delay10mSec(2);			// For display stable.
  		}
  		
  		//
 		PrintLcdStrLX(2, 0, "Write OK. Err   ");
 		SetCursorAddr(2, 14);
		PrintLcdDec(ErrorCount);
		Delay10mSec(200);		
 	}
 	
  }  // End of while(!SW16Pressed)
 		
}


//=============================================================================================
//Demo item (6)
//=============================================================================================
void DemoPWM()
{

  PrintLcdStrLX(1,0, "8bit PWM Demo   ");
  PrintLcdStrLX(2,0, "0,   H, 80H, FFH");
  
  PWM0Duty(0, 0);
  PWM1Duty(0, ADCDL);
  PWM2Duty(0, 0x80);
  PWM3Duty(0, 0xFF);
  PWM_EN(PWM_8BMODE, PWM_CH3_EN|PWM_CH2_EN|PWM_CH1_EN|PWM_CH0_EN);
  
  ADCInit(ADCC3_EN|ADCC2_EN|ADCC1_EN|ADCC0_EN, ADC_8BIT|ADC_CLK_DIV8);
  ADCDone = false;
  ADC_ChannelSel(ADC_CH0_IN);
  ADCStart();
  	
  while(!SW16Pressed)
  {

	if( ADCDone )
	{
		ADCDone = false;
		PWM1Duty(0, ADCDL);		// According ADC result, set new duty
				
		SetCursorAddr(2, 3);
		PrintLcdSpace(2);		// Clear number 
		SetCursorAddr(2, 3);
		PrintLcdHex(ADCDL);		// Write new number

		Delay1mSec(50);			// For display stable.
		
		ADCStart();
	}
  }
  
  PWM_OFF();	// All off
  
}









/*****************************************************************************
 * Processor:	SM59R16A2
 * Compiler:	Keil C 2.0
 *
 * Company:	SyncMOS Technologies International,Inc.
 * Author:	Stanley Huang
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * Board:	64-pin demo board (SDB0001A-0)
 * Purpose:
 *
 *
 *****************************************************************************/


